package winOrDie.Net;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;

import org.apache.xerces.impl.dv.DatatypeValidator;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import winOrDie.Application.WoD_Application;
import winOrDie.Application.WoD_Application_Data;
import winOrDie.Game.WoD_Game;
import winOrDie.Game.WoD_Player_Data;
import winOrDie.GameEngine.P2P.WoD_P2P_Peer;
import winOrDie.Net.Client.WoD_Peer;
import winOrDie.Net.Client.WoD_Peer_Editor;
import winOrDie.Net.Client.WoD_Peers_List;
import winOrDie.Net.Client.WoD_Peers_List_Editor;
import winOrDie.Net.RT.WoD_RT_Client_Movement;
import winOrDie.Net.RT.WoD_RT_Game_Info;
import winOrDie.Net.RT.WoD_RT_NTP_Message;
import winOrDie.Net.Server.WoD_Server_Client;
import winOrDie.Net.Server.WoD_Server_Client_List;
import winOrDie.Util.XML_Manager;

public class WoD_Net_Protocol_Manager 
{
	ByteArrayOutputStream byteArrayOutputStream = null;
	DataOutputStream dataOutputStream = null;
	
	ByteArrayInputStream byteArrayInputStream =null;
	DataInputStream dataInputStream = null;
	
	public WoD_Net_Protocol_Manager() {
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
	}
	
	/**
	 * This public method parses Header of message passed as parameter and returns it as {@link String}
	 * @param message
	 * @return {@link String}
	 * @throws Exception
	 */
	public String parse_Header(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		String Message_header = dataInputStream.readUTF();
		
		return Message_header;
	}
	
	/**
	 * This public method parses RT Header of message passed as parameter and returns it as byte
	 * @param message
	 * @return byte
	 * @throws Exception
	 */
	public byte parse_RT_Header(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		byte Message_header = dataInputStream.readByte();
		
		return Message_header;
	}
	
	public byte[] get_Chat_Message(String message) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Chat);
		dataOutputStream.writeUTF(message);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	public byte[] get_Game_Id_Message(String message) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Notify_Id_Game);
		dataOutputStream.writeUTF(message);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	
	public String parse_Chat_Message(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		String Message_header = dataInputStream.readUTF();
		
		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Chat))
		{
			Exception exception = new Exception("This message doesn't have a Chat Game message header.");
			throw exception;
		}
		
		String message_Content = dataInputStream.readUTF();
		return message_Content;
	}
	
	public String parse_READY_TO_PLAY(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);

		String Message_header = dataInputStream.readUTF();

		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Ready_to_Go))
		{
			Exception exception = new Exception("This message doesn't have a Ready to go message header.");
			throw exception;
		}

		String ScribeNodeID = dataInputStream.readUTF();
		return ScribeNodeID;
	}
	
	public String parse_READY_TO_PLAY_KO(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);

		String Message_header = dataInputStream.readUTF();

		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Ready_to_Go_KO))
		{
			Exception exception = new Exception("This message doesn't have a Ready to go message header.");
			throw exception;
		}

		String ScribeNodeID = dataInputStream.readUTF();
		return ScribeNodeID;
	}
	
	public String parse_NOT_READY_TO_PLAY(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);

		String Message_header = dataInputStream.readUTF();

		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Not_Ready_to_Go))
		{
			Exception exception = new Exception("This message doesn't have a Ready to go message header.");
			throw exception;
		}

		String ScribeNodeID = dataInputStream.readUTF();
		return ScribeNodeID;
	}
	
	public String parse_READY_TO_PLAY_OK(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		String Message_header = dataInputStream.readUTF();
		
		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Ready_to_Go_OK))
		{
			Exception exception = new Exception("This message doesn't have a ready to play Game message header.");
			throw exception;
		}
		
		String message_Content = dataInputStream.readUTF();
		return message_Content;
	}
	
	public String parse_Game_Id_Message(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		String Message_header = dataInputStream.readUTF();
		
		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Notify_Id_Game))
		{
			Exception exception = new Exception("This message doesn't have a Game Id message header.");
			throw exception;
		}
		
		String message_Content = dataInputStream.readUTF();
		return message_Content;
	}
	
	/**
	 * This public method returns formated Join Game message
	 * @param userName
	 * @param backup_Port
	 * @param RT_Port
	 * @param Voice_Port
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_Join_Game(WoD_Application_Data woDApplicationData) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameMenu.Join_Game);
		dataOutputStream.writeUTF(woDApplicationData.getWoDPlayerData().getUserName());
		dataOutputStream.writeUTF(woDApplicationData.getWoDConfiguration().getHost_Direction());
		dataOutputStream.writeInt(woDApplicationData.getWoDConfiguration().getControl_Port());
		dataOutputStream.writeInt(woDApplicationData.getWoDConfiguration().getRT_Port());
		dataOutputStream.writeInt(woDApplicationData.getWoDConfiguration().getVoice_Port());
		
		return byteArrayOutputStream.toByteArray();
	}
	
	
	/**
	 * This public method parses Join Game message passed as parameter and returns {@link WoD_Server_Client}
	 * @param message
	 * @return {@link WoD_Server_Client}
	 * @throws Exception
	 */
	public WoD_Server_Client parse_Join_Game(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		String Message_header = dataInputStream.readUTF();
		
		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameMenu.Join_Game))
		{
			Exception exception = new Exception("This message doesn't have a Join Game message header.");
			throw exception;
		}
		
		
		WoD_Server_Client woDServerClient = new WoD_Server_Client();
		woDServerClient.setUserName(dataInputStream.readUTF());
		woDServerClient.setHostDirection(dataInputStream.readUTF());
		woDServerClient.setTcp_backup(dataInputStream.readInt());
		woDServerClient.setUdp_port(dataInputStream.readInt());
		woDServerClient.setVoice_UDP_Port(dataInputStream.readInt());
		
		return woDServerClient;
	}

	
	
	/**
	 * This public method returns formated Join Game OK message
	 * @param woDApplicationData
	 * @param woDServerClient
	 * @return
	 * @throws Exception
	 */
	public byte[] get_Join_Game_OK(
			WoD_Application_Data woDApplicationData,
			WoD_Server_Client woDServerClient
			) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameMenu.Join_Game_OK);
		dataOutputStream.writeLong(
				woDApplicationData.getWoDGame().getID_Game()
				);
		dataOutputStream.writeUTF(woDApplicationData.getWoDGame().getGame_Title());
		dataOutputStream.writeInt(woDApplicationData.getWoDGame().getServer_RT_Port());
		
		return byteArrayOutputStream.toByteArray();
	}
	
	
	/**
	 * This public method parses Join Game OK message and modifies {@link WoD_Application_Data} passed as parameter
	 * @param message
	 * @param woDApplicationData
	 * @throws Exception
	 */
	public void parse_Join_Game_OK(byte[] message, WoD_Application_Data woDApplicationData) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		String Message_header = dataInputStream.readUTF();
		
		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameMenu.Join_Game_OK))
		{
			Exception exception = new Exception("This message doesn't have a Join Game OK message header.");
			throw exception;
		}
		
		woDApplicationData.getWoDGame().setID_Game(dataInputStream.readLong());
		woDApplicationData.getWoDGame().setGame_Title(dataInputStream.readUTF());
		woDApplicationData.getWoDGame().setServer_RT_Port(dataInputStream.readInt());
		
	}
	
	
	/**
	 * This public method returns formated Join Game KO message
	 * @param message
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_Join_Game_KO(String message) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameMenu.Join_Game_KO);
		dataOutputStream.writeUTF(message);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	
	/**
	 * This public method parses Join Game KO message and return response message as {@link String}
	 * @param message
	 * @return {@link String}
	 * @throws Exception
	 */
	public String parse_Join_Game_KO(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		String Message_header = dataInputStream.readUTF();
		
		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameMenu.Join_Game_KO))
		{
			Exception exception = new Exception("This message doesn't have a Join Game KO message header.");
			throw exception;
		}
		
		String Response_Message = dataInputStream.readUTF();
		return Response_Message;
		
	}
	
	
	
	/**
	 * This public method returns formated New User Info message
	 * @param woDServerClient
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_New_User_Info(WoD_Server_Client woDServerClient) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.New_User_Info);
		dataOutputStream.writeInt(woDServerClient.getCliend_Id());
		dataOutputStream.writeUTF(woDServerClient.getHostDirection());
		dataOutputStream.writeUTF(woDServerClient.getScribeNode_ID());
		dataOutputStream.writeUTF(woDServerClient.getUserName());
		dataOutputStream.writeInt(woDServerClient.getTcp_backup());
		dataOutputStream.writeInt(woDServerClient.getVoice_UDP_Port());
		dataOutputStream.writeBoolean(false);
		return byteArrayOutputStream.toByteArray();
	}
	
	
	/**
	 * This public method parses New User Info message and returns {@link WoD_Peer}
	 * @param message
	 * @return {@link WoD_Peer}
	 * @throws Exception
	 */
	public WoD_Peer parse_New_User_Info(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		String Message_header = dataInputStream.readUTF();
		
		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.New_User_Info))
		{
			Exception exception = new Exception("This message doesn't have a New User Ingo message header.");
			throw exception;
		}
		
		WoD_Peer woDPeer = new WoD_Peer();
		woDPeer.setCliend_Id(dataInputStream.readInt());
		woDPeer.setHostDirection(dataInputStream.readUTF());
		woDPeer.setScribeNode_ID(dataInputStream.readUTF());
		woDPeer.setUserName(dataInputStream.readUTF());
		woDPeer.setTcp_backup(dataInputStream.readInt());
		woDPeer.setVoice_UDP_Port(dataInputStream.readInt());
		woDPeer.setReadyToGo(false);
		
		return woDPeer;
	}
	
	
	/**
	 * This public method returns formated New User Info message
	 * @param woDServerClientList
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_Users_Info(WoD_Server_Client_List woDServerClientList) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		WoD_Peers_List woDPeersList = new WoD_Peers_List(woDServerClientList);
		XML_Manager xmlManager = new XML_Manager();
		
		
//		String XML_text = XML_Manager.DOM_AND_STRINGS.DOM2String(
//				WoD_Peers_List_Editor.get_Element_From_WoD_Peers_List(woDPeersList, xmlManager.createNewDocument()).getOwnerDocument()
//				);
		Document document = xmlManager.createNewDocument();
		Element element = WoD_Peers_List_Editor.get_Element_From_WoD_Peers_List(woDPeersList, document); 
		document.replaceChild(element, document.getDocumentElement());
		
		String XML_text = XML_Manager.DOM_AND_STRINGS.ParseXmlDocumentToString(
				document
			);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Users_Info);
		dataOutputStream.writeUTF(XML_text);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	
	/**
	 * This public method parses Users Info message and returns {@link WoD_Peers_List}
	 * @param message
	 * @return {@link WoD_Peers_List}
	 * @throws Exception
	 */
	public WoD_Peers_List parse_Users_Info(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		String Message_header = dataInputStream.readUTF();
		
		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Users_Info))
		{
			Exception exception = new Exception("This message doesn't have a Users Info message header.");
			throw exception;
		}
		
		String XML_String = dataInputStream.readUTF();
		
		Document document = XML_Manager.DOM_AND_STRINGS.ParseStringToXmlDocument(XML_String);
		WoD_Peers_List woDPeersList = WoD_Peers_List_Editor.get_WoD_Peers_List_From_Element(document.getDocumentElement());
		
		
		return woDPeersList;
	}
	
	
	/**
	 * This public method returns Node Down message
	 * @param ScribeNode_ID
	 * @return
	 * @throws Exception
	 */
	public byte[] get_NODE_DOWN(String ScribeNode_ID) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(ScribeNode_ID);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	/**
	 * This public method parses Users Info message and returns Scribe node ID String 
	 * @param message
	 * @return {@link String}
	 * @throws Exception
	 */
	public String parse_NODE_DOWN(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		String ScribeNodeID = dataInputStream.readUTF();
		return ScribeNodeID;
		
	}
	
	
	/**
	 * This public method returns Leave message
	 * @param ScribeNode_ID
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_LEAVE_GAME(String ScribeNode_ID) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Leave_Game);
		dataOutputStream.writeUTF(ScribeNode_ID);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	/**
	 * This public method parses Leave game message and returns Scribe node ID String 
	 * @param message
	 * @return
	 * @throws Exception
	 */
	public String parse_LEAVE_GAME(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);

		String Message_header = dataInputStream.readUTF();

		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Leave_Game))
		{
			Exception exception = new Exception("This message doesn't have a Users Info message header.");
			throw exception;
		}

		String ScribeNodeID = dataInputStream.readUTF();
		return ScribeNodeID;

	}

	
	/**
	 * This public method returns select side message
	 * @param Team_Code
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_SELECT_SIDE(String Team_Code) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Select_Side);
		dataOutputStream.writeUTF(Team_Code);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	/**
	 * This public method returns Select Captain Rol message
	 * @param Team_Code
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_SELECT_ROL(String Rol_Code) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol);
		dataOutputStream.writeUTF(Rol_Code);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	/**
	 * This public method returns ready to play message
	 * @param Team_Code
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_READY_TO_PLAY() throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Ready_to_Go);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	
	/**
	 * This public method returns ready to play ko message
	 * @param Team_Code
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_READY_TO_PLAY_KO() throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Ready_to_Go_KO);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	/**
	 * This public method returns read to play message
	 * @param Team_Code
	 * @return byte[]
	 * @throws Exception
	 */

	public byte[] get_READY_TO_PLAY_OK(String ScribeNode_ID) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Ready_to_Go_OK);
		dataOutputStream.writeUTF(ScribeNode_ID);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	//get_NOT_READY_TO_PLAY
	/**
	 * This public method returns read to play ko message to members
	 * @param Team_Code
	 * @return byte[]
	 * @throws Exception
	 */

	public byte[] get_NOT_READY_TO_PLAY(String ScribeNode_ID) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Not_Ready_to_Go);
		dataOutputStream.writeUTF(ScribeNode_ID);
		
		return byteArrayOutputStream.toByteArray();
	}
	/**
	 * This public method returns force start message
	 * @param Team_Code
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_FORCE_START(WoD_Server_Client_List woDServerClientList, WoD_Application_Data woDApplicationData) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Force_Start);
		dataOutputStream.writeUTF(woDApplicationData.getWoDConfiguration().getHost_Direction());
		dataOutputStream.writeInt(woDApplicationData.getWoDConfiguration().getRT_Port());
		
		
		WoD_Peers_List woDPeersList = new WoD_Peers_List(woDServerClientList);
		XML_Manager xmlManager = new XML_Manager();
		
		
//		String XML_text = XML_Manager.DOM_AND_STRINGS.DOM2String(
//				WoD_Peers_List_Editor.get_Element_From_WoD_Peers_List(woDPeersList, xmlManager.createNewDocument()).getOwnerDocument()
//				);
		Document document = xmlManager.createNewDocument();
		Element element = WoD_Peers_List_Editor.get_Element_From_WoD_Peers_List(woDPeersList, document); 
		document.replaceChild(element, document.getDocumentElement());
		
		String XML_text = XML_Manager.DOM_AND_STRINGS.ParseXmlDocumentToString(
				document
			);
		
		dataOutputStream.writeUTF(XML_text);		
		
		return byteArrayOutputStream.toByteArray();
	}
	
	public WoD_Peers_List parse_FORCE_START(byte[] message, WoD_Application_Data woDApplicationData) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);

		String Message_header = dataInputStream.readUTF();
		woDApplicationData.getWoDGame().setServerHost(dataInputStream.readUTF());
		woDApplicationData.getWoDGame().setServer_RT_Port(dataInputStream.readInt());

		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Force_Start))
		{
			Exception exception = new Exception("This message doesn't have a Force Start message header.");
			throw exception;
		}
		
		String XML_String = dataInputStream.readUTF();
		
		Document document = XML_Manager.DOM_AND_STRINGS.ParseStringToXmlDocument(XML_String);
		WoD_Peers_List woDPeersList = WoD_Peers_List_Editor.get_WoD_Peers_List_From_Element(document.getDocumentElement());
		
		return woDPeersList;
	}
	
	
	/**
	 * This public method parses Select side message and returns team code String 
	 * @param message
	 * @return {@link String}
	 * @throws Exception
	 */
	public String parse_SELECT_SIDE(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);

		String Message_header = dataInputStream.readUTF();

		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Side))
		{
			Exception exception = new Exception("This message doesn't have a Select Side message header.");
			throw exception;
		}

		String team = dataInputStream.readUTF();
		return team;

	}
	
	/**
	 * This public method parses Select side message and returns team code String 
	 * @param message
	 * @return {@link String}
	 * @throws Exception
	 */
	public String parse_SELECT_ROL(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);

		String Message_header = dataInputStream.readUTF();

		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol))
		{
			Exception exception = new Exception("This message doesn't have a Select Side message header.");
			throw exception;
		}

		String rol = dataInputStream.readUTF();
		return rol;
	}
	
	
	/**
	 * This public method returns Select side OK message
	 * @param ScribeNode_ID
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_SELECT_SIDE_OK(String TEAM_CODE) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Select_Side_OK);
		dataOutputStream.writeUTF(TEAM_CODE);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	/**
	 * This public method returns Select role OK message
	 * @param ScribeNode_ID
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_SELECT_ROLE_OK(String ROLE_CODE) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol_OK);
		dataOutputStream.writeUTF(ROLE_CODE);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	/**
	 * This public method returns Select role OK message
	 * @param ScribeNode_ID
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_SELECT_MAP(String MAP_CODE) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Change_Map);
		dataOutputStream.writeUTF(MAP_CODE);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	/**
	 * This public method returns Select role KO message
	 * @param ScribeNode_ID
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_SELECT_ROLE_KO(String message) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol_KO);
		dataOutputStream.writeUTF(message);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	
	/**
	 * This public method parses Select side OK message and returns team code String 
	 * @param message
	 * @return {@link String}
	 * @throws Exception
	 */
	public String parse_SELECT_SIDE_OK(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);

		String Message_header = dataInputStream.readUTF();

		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Side_OK))
		{
			Exception exception = new Exception("This message doesn't have a Select Side OK message header.");
			throw exception;
		}

		String team = dataInputStream.readUTF();
		return team;

	}
	
	/**
	 * This public method parses Select role OK message and returns role code String 
	 * @param message
	 * @return {@link String}
	 * @throws Exception
	 */
	public String parse_SELECT_ROLE_OK(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);

		String Message_header = dataInputStream.readUTF();

		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol_OK))
		{
			Exception exception = new Exception("This message doesn't have a Select Side OK message header.");
			throw exception;
		}

		String role = dataInputStream.readUTF();
		return role;

	}
	
	/**
	 * This public method parses Select Map message and returns role code String 
	 * @param message
	 * @return {@link String}
	 * @throws Exception
	 */
	public String parse_SELECT_MAP(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);

		String Message_header = dataInputStream.readUTF();

		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Change_Map))
		{
			Exception exception = new Exception("This message doesn't have a Select Side OK message header.");
			throw exception;
		}

		String map = dataInputStream.readUTF();
		return map;
	}
	
	
	/**
	 * This public method returns Select side KO message
	 * @param ScribeNode_ID
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_SELECT_SIDE_KO(String message) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Select_Side_KO);
		dataOutputStream.writeUTF(message);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	/**
	 * This public method parses Select side KO message and returns message String 
	 * @param message
	 * @return {@link String}
	 * @throws Exception
	 */
	public String parse_SELECT_SIDE_KO(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);

		String Message_header = dataInputStream.readUTF();

		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Side_KO))
		{
			Exception exception = new Exception("This message doesn't have a Select Side KO message header.");
			throw exception;
		}

		String message_Received = dataInputStream.readUTF();
		return message_Received;

	}
	
	
	/**
	 * This public method returns Select side INFO message
	 * @param P2P_ID
	 * @param TeamCode
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_SELECT_SIDE_INFO(String P2P_ID, String TeamCode) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Select_Side_Info);
		dataOutputStream.writeUTF(P2P_ID);
		dataOutputStream.writeUTF(TeamCode);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	/**
	 * This public method returns Select role INFO message
	 * @param P2P_ID
	 * @param RoleCode
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_SELECT_ROLE_INFO(String P2P_ID, String RoleCode) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol_Info);
		dataOutputStream.writeUTF(P2P_ID);
		dataOutputStream.writeUTF(RoleCode);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	
	/**
	 * This public method parses Select side Info message and returns message {@link WoD_Peer} 
	 * @param message
	 * @return {@link WoD_Peer}
	 * @throws Exception
	 */
	public WoD_Peer parse_SELECT_SIDE_INFO(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);

		String Message_header = dataInputStream.readUTF();

		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Side_Info))
		{
			Exception exception = new Exception("This message doesn't have a Select Side Info message header.");
			throw exception;
		}

		WoD_Peer woDPeer = new WoD_Peer();
		woDPeer.setScribeNode_ID(dataInputStream.readUTF());
		
		String TEAM_Code = dataInputStream.readUTF();
		if (TEAM_Code.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Side_OPTION_GoodTeam))
		{
			woDPeer.setTeam(WoD_Game.Game_Teams.Captain_Team);
		}
		else if (TEAM_Code.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Side_OPTION_PiratesTeam))
		{
			woDPeer.setTeam(WoD_Game.Game_Teams.Pirates_Team);
		}
		else
		{
			Exception exception = new Exception("Unknown Team");
			throw exception;
		}
		
		return woDPeer;

	}
	
	/**
	 * This public method parses Select side Info message and returns message {@link WoD_Peer} 
	 * @param message
	 * @return {@link WoD_Peer}
	 * @throws Exception
	 */
	public WoD_Peer parse_SELECT_ROLE_INFO(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);

		String Message_header = dataInputStream.readUTF();

		if (!Message_header.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol_Info))
		{
			Exception exception = new Exception("This message doesn't have a Select Side Info message header.");
			throw exception;
		}

		WoD_Peer woDPeer = new WoD_Peer();
		woDPeer.setScribeNode_ID(dataInputStream.readUTF());
		
		String ROLE_Code = dataInputStream.readUTF();
		if (ROLE_Code.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol_OPTION_Captain))
		{
			woDPeer.setROL(WoD_Game.Game_Rols.Captain);
		}
		else if (ROLE_Code.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol_OPTION_Maiden))
		{
			woDPeer.setROL(WoD_Game.Game_Rols.Princess);
		}
		else
		{
			Exception exception = new Exception("Unknown Role");
			throw exception;
		}
		
		return woDPeer;

	}
	
	
	/**
	 * This public method returns RT movement message
	 * @param movement
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_RT_Movement(WoD_RT_Client_Movement clientMovement) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeByte(WoD_Net_Protocol_ASCII.RealTime.HEADER_GAME_ACTION);
		dataOutputStream.writeInt(clientMovement.getID());
		dataOutputStream.writeInt(clientMovement.getX());
		dataOutputStream.writeInt(clientMovement.getY());
		dataOutputStream.writeLong(clientMovement.getTimeStamp());
		
		return byteArrayOutputStream.toByteArray();
	}
	
	
	/**
	 * This public method parses RT movement message and returns movement code byte 
	 * @param message
	 * @return {@link WoD_RT_Client_Movement}
	 * @throws Exception
	 */
	public WoD_RT_Client_Movement parse_RT_Movement(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		byte header = dataInputStream.readByte();
		if (header != WoD_Net_Protocol_ASCII.RealTime.HEADER_GAME_ACTION)
		{
			Exception exception = new Exception("This message doesn't have a RT Movement message header.");
			throw exception;
		}
		
		WoD_RT_Client_Movement clientMovement = new WoD_RT_Client_Movement();
		clientMovement.setID(dataInputStream.readInt());
		clientMovement.setX(dataInputStream.readInt());
		clientMovement.setY(dataInputStream.readInt());
		clientMovement.setTimeStamp(dataInputStream.readLong());
		
		return clientMovement;
	}
	
	
	/**
	 * This public method returns GAME RT info message
	 * @param gameRTInfo
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_Game_RT_Info(WoD_RT_Game_Info gameRTInfo) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeByte(WoD_Net_Protocol_ASCII.RealTime.HEADER_GAME_ACTION);
		dataOutputStream.writeInt(gameRTInfo.get_Num_Players());
		dataOutputStream.writeLong(gameRTInfo.getTimeStamp());
		
		for (WoD_RT_Client_Movement clientMovement : gameRTInfo.getClientMovements()) {
			dataOutputStream.writeInt(clientMovement.getX());
			dataOutputStream.writeInt(clientMovement.getY());
			dataOutputStream.writeInt(clientMovement.getID());
			dataOutputStream.writeLong(clientMovement.getTimeStamp());
		}
		dataOutputStream.writeInt(gameRTInfo.getGameState());
		
		return byteArrayOutputStream.toByteArray();
	}

	
	/**
	 * This public method parses GAME RT Info message and returns {@link WoD_RT_Game_Info} object
	 * @param message
	 * @return {@link WoD_RT_Game_Info}
	 * @throws Exception
	 */
	public WoD_RT_Game_Info parse_GAME_RT_INFO(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		byte header = dataInputStream.readByte();
		if (header != WoD_Net_Protocol_ASCII.RealTime.HEADER_GAME_ACTION)
		{
			Exception exception = new Exception("This message doesn't have a Game RT Info message header.");
			throw exception;
		}
		

		int num_clients = dataInputStream.readInt();
		long time_Stamp = dataInputStream.readLong();
		
		WoD_RT_Game_Info gameRTInfo = new WoD_RT_Game_Info();
		gameRTInfo.setTimeStamp(time_Stamp);
		
		for (int position = 0; position < num_clients; position++) {
			WoD_RT_Client_Movement clientMovement = new WoD_RT_Client_Movement();
			clientMovement.setX(dataInputStream.readInt());
			clientMovement.setY(dataInputStream.readInt());
			clientMovement.setID(dataInputStream.readInt());
			clientMovement.setTimeStamp(dataInputStream.readLong());
			gameRTInfo.getClientMovements().add(clientMovement);
		}
		gameRTInfo.setGameState(dataInputStream.readInt());
		
		return gameRTInfo;
	}
	
	/**
	 * This public method returns NTP RT client message
	 * @param timestamp
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_RT_NTP_CLIENT_MESSAGE(WoD_RT_NTP_Message woDNTPMessage) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeByte(WoD_Net_Protocol_ASCII.RealTime.HEADER_SNTP);
		dataOutputStream.writeInt(woDNTPMessage.getID());
		dataOutputStream.writeLong(woDNTPMessage.getTS_CS());
		
		return byteArrayOutputStream.toByteArray();
	}
	
	
	/**
	 * This public method parses NTP client message and returns {@link WoD_RT_NTP_Message}
	 * @param message
	 * @return {@link WoD_RT_NTP_Message}
	 * @throws Exception
	 */
	public WoD_RT_NTP_Message parse_RT_NTP_CLIENT_MESSAGE(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		byte header = dataInputStream.readByte();
		if (header != WoD_Net_Protocol_ASCII.RealTime.HEADER_SNTP)
		{
			Exception exception = new Exception("This message doesn't have a Game SNTP message header.");
			throw exception;
		}
		
		WoD_RT_NTP_Message woDNTPMessage = new WoD_RT_NTP_Message();
		woDNTPMessage.setID(dataInputStream.readInt());
		woDNTPMessage.setTS_CS(dataInputStream.readLong());
		
		return woDNTPMessage;
	}
	
	
	/**
	 * This public method returns NTP RT Server message
	 * @param woDNTPMessage
	 * @return byte[]
	 * @throws Exception
	 */
	public byte[] get_RT_NTP_SERVER_MESSAGE(WoD_RT_NTP_Message woDNTPMessage) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeByte(WoD_Net_Protocol_ASCII.RealTime.HEADER_SNTP);
		
		dataOutputStream.writeLong(woDNTPMessage.getTS_CS());
		dataOutputStream.writeLong(woDNTPMessage.getTS_SS());
		dataOutputStream.writeLong(woDNTPMessage.getTS_SR());
		
		return byteArrayOutputStream.toByteArray();

	}
	
	
	/**
	 * This public method parses NTP Server message and returns {@link WoD_RT_NTP_Message}
	 * @param message
	 * @return {@link WoD_RT_NTP_Message}
	 * @throws Exception
	 */
	public WoD_RT_NTP_Message parse_RT_NTP_SERVER_MESSAGE(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		byte header = dataInputStream.readByte();
		if (header != WoD_Net_Protocol_ASCII.RealTime.HEADER_SNTP)
		{
			Exception exception = new Exception("This message doesn't have a Game SNTP message header.");
			throw exception;
		}
		
		WoD_RT_NTP_Message woDNTPMessage = new WoD_RT_NTP_Message();
		woDNTPMessage.setTS_CS(dataInputStream.readLong());
		woDNTPMessage.setTS_SS(dataInputStream.readLong());
		woDNTPMessage.setTS_SR(dataInputStream.readLong());
		
		return woDNTPMessage;
	}
	
	public byte[] get_RT_CLIENT_SYNC_INFO(int delay) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.RealTime_Control.Synchronism_Info);
		dataOutputStream.writeInt(delay);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	
	public int parse_RT_CLIENT_SYNC_INFO(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		String header = dataInputStream.readUTF();
		if (!header.equals(WoD_Net_Protocol_ASCII.RealTime_Control.Synchronism_Info))
		{
			Exception exception = new Exception("This message doesn't have a RT client Sync Info message header.");
			throw exception;
		}
		
		int delay = dataInputStream.readInt();
		return delay;
		
	}
	
	public byte[] get_COUNT_DOWN(Long ts) throws Exception
	{
		byteArrayOutputStream = new ByteArrayOutputStream();
		dataOutputStream = new DataOutputStream(byteArrayOutputStream);
		
		dataOutputStream.writeUTF(WoD_Net_Protocol_ASCII.RealTime_Control.Count_Down);
		dataOutputStream.writeLong(ts);
		
		return byteArrayOutputStream.toByteArray();
	}
	
	
	public long parse_COUNT_DOWN(byte[] message) throws Exception
	{
		byteArrayInputStream = new ByteArrayInputStream(message);
		dataInputStream = new DataInputStream(byteArrayInputStream);
		
		String header = dataInputStream.readUTF();
		if (!header.equals(WoD_Net_Protocol_ASCII.RealTime_Control.Count_Down))
		{
			Exception exception = new Exception("This message doesn't have a Count Down message header.");
			throw exception;
		}
		
		long timeStart = dataInputStream.readLong();
		return timeStart;
	}
}

